package cloud.pangui.core.mongo.utils;

import com.mongodb.MongoException;
import cloud.pangui.core.mongo.element.Cond;
import cloud.pangui.core.mongo.element.Ele;
import cloud.pangui.core.mongo.element.Value;
import cloud.pangui.core.mongo.operate.Where;

import java.util.ArrayList;
import java.util.List;

/**
 * @Auther hepangui
 * @Date 2020/10/06 0001
*/
public class SqlWhereParseUtils {

	/**
	 * 逐个解析str
	 * a=1 and b=2 and c=3 or d=4 and (e=5 or f=6) and m in asdasda
	 * where 条件不支持嵌套括号 且括号内部只允许使用or
	 * 简单模式下不允许使用函数，使用多次andor（因为后面的会覆盖前面的）
	 * @param whereStr
	 */
	public static Where parseWhere(String whereStr) {
		// 首先假设这是一个简单的where表达式，
		// 私以为简单的表达式至少会占到应用的80%以上
		// 当在解析过程中遇到函数，或者运算等，再重新使用复杂模式获取
		try{
			return parseWhere(whereStr,Where.SIMPLE_MODE);
		}catch (Where.CondNotSupportInSimpleModeException e){
			return parseWhere(whereStr,Where.COMPLEX_MODE);
		}
	}

	/**
	 * 解析where条件，并指定解析模式，update，delete是必须为简单模式
	 * query时参考上面的方法
	 * @param whereStr
	 * @param mode
	 * @return
	 */
	public static Where parseWhere(String whereStr, int mode) {
		Where whereCondition = new Where(mode);

		String upperStr = whereStr.toUpperCase();
		boolean nextIsAnd = true;//第一个操作符是and，后面的后续的字符串来解析
		StringBuilder sb = new StringBuilder("");
		for (int i = 0; i < whereStr.length(); i++) {
			char c = whereStr.charAt(i);
			if(c == '\\'){//转义符，取后一位
				c = whereStr.charAt(i+1);
				i = i+1;
			}
			// and，或or之后，直接跟了一个括号，表示后面是一个组合的or条件
			if (sb.length() == 0 && c == '(') {
				// 括号内部的几个or条件
				int endIndex = whereStr.indexOf(")", i + 1);
				String substring = whereStr.substring(i + 1, endIndex);
				String replace = substring.replace(" or ", " OR ");
				String[] split = replace.split(" OR ");
				Cond[] conds = new Cond[split.length];
				for (int j = 0; j < split.length; j++) {
					conds[j] = parseWhereEle(split[j]);
				}
				whereCondition.andOr(conds);
				i = endIndex;
				continue;
			}
			// 匹配 “ and ” “)and ” " and("
			if (i + 4 < whereStr.length() && (c == ' ' || c == ')') && upperStr.charAt(i + 1) == 'A'
					&& upperStr.charAt(i + 2) == 'N' && upperStr.charAt(i + 3) == 'D'
					&& (upperStr.charAt(i + 4) == ' ' || upperStr.charAt(i + 4) == '(')) {
				i += " AND".length() - 1;//i本身有i++
				if (sb.length() > 0) { // (a=1 or b=2) and c=3   当解析到and时，前方括号已经处理过了，所以要求length>0
					Cond where = parseWhereEle(sb.toString());
					if (nextIsAnd) {
						whereCondition.and(where);
					} else {
						whereCondition.or(where);
					}
					sb = new StringBuilder("");
				}
				nextIsAnd = true;
			} else if (i + 3 < whereStr.length() && c == ' ' && upperStr.charAt(i + 1) == 'O'
					&& upperStr.charAt(i + 2) == 'R' && upperStr.charAt(i + 3) == ' ') {
				Cond where = parseWhereEle(sb.toString());
				i += " OR".length() - 1;//i本身有i++
				if (nextIsAnd) {
					whereCondition.and(where);
				} else {
					whereCondition.or(where);
				}
				sb = new StringBuilder("");
				nextIsAnd = false;
			} else {
				// 首字符不为空
				if (sb.length() != 0 || c != ' ') {
					sb.append(c);
				}
			}
		}
		if (sb.length() > 0) {
			Cond where = parseWhereEle(sb.toString());
			if (nextIsAnd) {
				whereCondition.and(where);
			} else {
				whereCondition.or(where);
			}
		}
		return whereCondition;
	}


	/**
	 * 正常的where条件
	 */
	static String[] symbols = new String[]{">=", "<=", "<>", "!=", ">", "<", "=", " like ", " LIKE "};

	/**
	 * in操作
	 */
	static String[] symbols1 = new String []{" NOT IN "," not in ", " in ", " IN "};

	/**
	 * 包含括号的
	 */
	static String[] symbols2 = new String[]{" in(", " not in(", " IN(", " NOT IN("};
	static String[] symbols3 = new String[]{" is ", " IS "};

	/**
	 * 将构建where条件
	 *
	 * @param eleStr
	 * @return
	 */
	public static Cond parseWhereEle(String eleStr) {
		for (String symbol : symbols) {
			if (eleStr.indexOf(symbol) > -1) {
				Cond where = parseBySymbol(eleStr, symbol);
				return where;
			}
		}
		for (String symbol : symbols1) {
			if (eleStr.indexOf(symbol) > -1) {
				Cond where = parseBySymbolIn(eleStr, symbol);
				return where;
			}
		}
		for (String symbol : symbols2) {
			if (eleStr.indexOf(symbol) > -1) {
				Cond where = parseBySymbolIn(eleStr.replace(symbol, symbol.replace("(", " ("))
						, symbol.substring(0, symbol.length() - 1));
				return where;
			}
		}
		for (String symbol : symbols3) {
			if (eleStr.indexOf(symbol) > -1) {
				Cond where = parseBySymbolNull(eleStr, symbol);
				return where;
			}
		}
		throw new MongoException("不支持的condition表达式：" + eleStr);
	}

	private static Cond parseBySymbolNull(String eleStr, String symbol) {
		String[] split1 = eleStr.split(symbol);
		if (split1.length != 2) {
			throw new MongoException("错误的where表达式：" + eleStr);
		}



		Ele key = SqlEleParseUtil.parseEle(split1[0]);
		if(split1[1].indexOf("not")>-1 || split1[1].indexOf("NOT")>-1){
			return Cond.isNotNull(key);
		}else{
			return Cond.isNull(key);
		}
	}


	/**
	 * 中间符号是in
	 * @param eleStr
	 * @param symbol
	 * @return
	 */
	private static Cond parseBySymbolIn(String eleStr, String symbol) {
		String[] split1 = eleStr.split(symbol);
		if (split1.length != 2) {
			throw new MongoException("错误的where表达式：" + eleStr);
		}
		Ele key = SqlEleParseUtil.parseEle(split1[0]);

		// 去除外层括号
		String trim = split1[1].trim();
		String noBacketStr = trim.substring(1, trim.length() - 1);
		if(!SqlEleParseUtil.isSimpleEle(noBacketStr)){
			throw new MongoException("in操作中不允许使用函数或复杂表达式");
		}
		String[] valuesInBacket = noBacketStr.split(",");
		List ins = new ArrayList();
		for (String s : valuesInBacket) {
			Ele ele = SqlEleParseUtil.parseEle(s);
			ins.add(ele.toExpression());
		}
		Ele value = Value.of(ins);
		return Cond.ofSymbol(symbol.trim(), key, value);
	}

	/**
	 * 按中间符号进行拆分
	 *
	 * @param eleStr a>=1
	 * @param symbol >=
	 * @return
	 */
	private static Cond parseBySymbol(String eleStr, String symbol) {
		String[] split1 = eleStr.split(symbol);
		if (split1.length != 2) {
			throw new MongoException("错误的where表达式：" + eleStr);
		}
		Ele key = SqlEleParseUtil.parseEle(split1[0]);
		Ele value = SqlEleParseUtil.parseEle(split1[1]);
		return Cond.ofSymbol(symbol.trim(), key, value);
	}


}
